package com.xiang.ad.mysql.dto;

import com.xiang.ad.mysql.constant.OpType;
import lombok.Data;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;

/**
 * Created by xiang.
 * 对模板文件进行解析，传入对应的template文件，解析所有的操作对map进行填充
 */
@Data
public class ParseTemplate {

    //标识监听的数据库 就是模板文件中声明的数据库
    private String database;

    // 表的名称（database的标识）-模板文件的各个定义
    private Map<String, TableTemplate> tableTemplateMap = new HashMap<>();

    //将模板文件中的文件进行解析
    public static ParseTemplate parse(Template _template) {
        //设置好数据库的名字
        ParseTemplate template = new ParseTemplate();
        template.setDatabase(_template.getDatabase()); //设置对哪个数据库进行解析

        // 对template中的tablelist进行遍历
        for (JsonTable table : _template.getTableList()) {

            String name = table.getTableName();//获取数据表的名字
            Integer level = table.getLevel();//层级
            //每个表都new一个tableTemplate
            TableTemplate tableTemplate = new TableTemplate();
            tableTemplate.setTableName(name); //设置模板的name
            tableTemplate.setLevel(level.toString()); //设置模板的level
            template.tableTemplateMap.put(name, tableTemplate);//map填充

            //遍历 操作类型对应的列      操作类型-字段的顺序
            Map<OpType, List<String>> opTypeFieldSetMap = tableTemplate.getOpTypeFieldSetMap();

            /**
             * 实现对opTypeFieldSetMap的填充
             * 1、对insert中支持的所有的列进行遍历，遍历的时候将tableTemplate中对应的操作类型的map取出来
             * 2、一开始对应的opType可能是不存在的，通过getAndCreateIfNeed获取，
             * 3、对拿到的结果 操作（添加、更新、删除）列
             */
            for (JsonTable.Column column : table.getInsert()) {
                //从map中按key取值，如果取不到则会创建并加入到map中，返回创建的对象
                getAndCreateIfNeed(
                        OpType.ADD,//insert类型
                        opTypeFieldSetMap,
                        ArrayList::new
                ).add(column.getColumn());
            }
            for (JsonTable.Column column : table.getUpdate()) {
                getAndCreateIfNeed(
                        OpType.UPDATE,//update类型
                        opTypeFieldSetMap,
                        ArrayList::new
                ).add(column.getColumn());
            }
            for (JsonTable.Column column : table.getDelete()) {
                getAndCreateIfNeed(
                        OpType.DELETE,//delete类型
                        opTypeFieldSetMap,
                        ArrayList::new
                ).add(column.getColumn());
            }
        }

        return template;
    }

    //如果key存在，则查询value取值，如果不存在，以key为key，new新的value
    private static <T, R> R getAndCreateIfNeed(T key,
                                               Map<T, R> map,
                                               Supplier<R> factory) {
        return map.computeIfAbsent(key, k -> factory.get());
    }
}
